package com.sangmo.fts.common.authority.filters;

import com.sangmo.boot.framework.common.session.UserSession;
import com.sangmo.boot.framework.common.utils.UnderlineToCamelUtils;
import com.sangmo.fts.common.authority.EntitySearchContext;
import com.sangmo.fts.common.authority.IAuthorityFilter;
import com.sangmo.fts.common.authority.meta.PropertyCheckAnn;
import com.sangmo.fts.common.authority.sql.NativeSearchContext;

import javax.persistence.criteria.Path;
import javax.persistence.criteria.Predicate;

/*
* 解决了权限依赖项目主体对象的问题
* */
public class PropertyCheckFilter implements IAuthorityFilter<PropertyCheckAnn> {

    @Override
    public Class<PropertyCheckAnn> getAnnotation() {
        return PropertyCheckAnn.class;
    }

    @Override
    public IAuthorityFilter.SearchFilterResult internalSearchFilter(EntitySearchContext context, PropertyCheckAnn annotation, int expectedRight) {

        Path path = context.getRoot().get(annotation.indicator());
        Predicate p1 = null;
        if ("<>".equals(annotation.operator())) {
            p1 = context.getCriteriaBuilder().notEqual(path, convert(annotation.propertyClass(), annotation.value()));
        } else {
            p1 = context.getCriteriaBuilder().equal(path, convert(annotation.propertyClass(), annotation.value()));
        }

        return new SearchFilterResult().setPredicate(p1);
    }

    @Override
    public NativeSearchFilterResult internalNativeSearchFilter(NativeSearchContext context, PropertyCheckAnn annotation, int expectedRight) {
        NativeSearchFilterResult nativeSearchFilterResult = new NativeSearchFilterResult();

        String var = context.createVar();
        nativeSearchFilterResult.setSql(String.format("%s.%s %s :%s",
                context.getAlias(), UnderlineToCamelUtils.camelToUnderline(annotation.indicator()), annotation.operator(), var
        ));

        nativeSearchFilterResult.getVariables().put(var, convert(annotation.propertyClass(), annotation.value()));
        return nativeSearchFilterResult;
    }

    private Object convert(Class clazz, String value) {
        if ("$user".equals(value)) {
            return UserSession.getUserInterface().getId();
        }

        if (clazz.isAssignableFrom(Boolean.class)) {
            return Boolean.valueOf(value.toString());
        } else if (clazz.isAssignableFrom(Integer.class)) {
            return Integer.valueOf(value.toString(), 10);
        }
        return value;
    }
}
